
<!DOCTYPE html>
<html lang="">


<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
  <meta name="theme-color" content="#202020"/>
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <script src="/js/busuanzi.pure.mini.js" async></script>
  
  
    <meta name="keywords" content="Java,Spring,SpringFramework," />
  

  
    <meta name="description" content="一个专注一coding的网站。提供丰富编程知识，包括Spring、Java、EmberJS、SpringBoot等等技术。" />
  
  
  <link rel="icon" type="image/x-icon" href="/image/favicon.ico">
  <title>Spring Framework5.x [ Keep Coding ]</title>
  
    <!-- stylesheets list from config.yml -->
    
      <link rel="stylesheet" href="/css/pure-min.css">
    
      <link rel="stylesheet" href="/css/xoxo.css">
    
  
<meta name="generator" content="Hexo 5.0.2"><link rel="alternate" href="/atom.xml" title="Keep Coding" type="application/atom+xml">
</head>

<body>
  <div class="nav-container">
    <nav class="home-menu pure-menu pure-menu-horizontal">
  <a class="pure-menu-heading" href="/">
    <img class="avatar" src="/image/favicon.ico">
    <span class="title">Keep Coding</span>
  </a>

  <ul class="pure-menu-list clearfix">
      
          
            <li class="pure-menu-item"><a href="/" class="pure-menu-link">首页</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/archives" class="pure-menu-link">归档</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/tags" class="pure-menu-link">标签</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/search" class="pure-menu-link">搜索</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/about" class="pure-menu-link">关于</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/atom.xml" class="pure-menu-link">订阅</a></li>
          
      
  </ul>
   
</nav>
  </div>

  <div class="container" id="content-outer">
    <div class="inner" id="content-inner">
      <div class="post-container">
  <article class="post" id="post">
    <header class="post-header text-center">
      <h1 class="title">
        Spring Framework5.x
      </h1>
      <span>
        
        <time class="time" datetime="2020-05-04T08:13:56.000Z">
        2020-05-04
      </time>
        
      </span>
      <span class="slash">/</span>
      <span class="post-meta">
      <span class="post-tags">
        <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Java/" rel="tag">Java</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Spring/" rel="tag">Spring</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/SpringFramework/" rel="tag">SpringFramework</a></li></ul>
      </span>
    </span>
      <span class="slash">/</span>
      <span class="read">
      <span id="busuanzi_value_page_pv"></span> 点击
    </span>
      <span class="slash">/</span>
      <span class="read">阅读耗时 10 分钟</span>
    </header>

    <div class="post-content">
      <h1 id="Spring-Framework5-x"><a href="#Spring-Framework5-x" class="headerlink" title="Spring Framework5.x"></a>Spring Framework5.x</h1><h2 id="BeanDefinition对象"><a href="#BeanDefinition对象" class="headerlink" title="BeanDefinition对象"></a>BeanDefinition对象</h2><p>Bean定义主要对象包括如下几个属性：</p>
<table>
<thead>
<tr>
<th>Property</th>
<th align="right">描述</th>
</tr>
</thead>
<tbody><tr>
<td>Class</td>
<td align="right"><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-class">bean实例</a></td>
</tr>
<tr>
<td>Name</td>
<td align="right"><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-beanname">Bean名称</a></td>
</tr>
<tr>
<td>Scope</td>
<td align="right"><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-scopes">Bean类型（单例、原型..)</a></td>
</tr>
<tr>
<td>构造函数参数</td>
<td align="right"><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-collaborators">Dependency Injection</a></td>
</tr>
<tr>
<td>Properties</td>
<td align="right"><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-collaborators">Dependency Injection</a></td>
</tr>
<tr>
<td>Autowirging mode</td>
<td align="right"><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-autowire">自动注入模型</a></td>
</tr>
<tr>
<td>Lazy initizlization</td>
<td align="right"><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-lazy-init">懒加载模型</a></td>
</tr>
<tr>
<td>Iniitialization method</td>
<td align="right"><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-lifecycle-initializingbean">初始化方法</a></td>
</tr>
<tr>
<td>Destruction method</td>
<td align="right"><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-lifecycle-disposablebean">销毁方法</a></td>
</tr>
</tbody></table>
<p>bean定义所有属性大概有上百个。就以最常用的<code>RootBeanDefinition</code>为例，这个类是bean定义最核心的实现类。类中定义非常多属性，这些属性都是bean的定义信息。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** Map with String keys and Object values. */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> Map&lt;String, Object&gt; attributes = <span class="keyword">new</span> LinkedHashMap&lt;&gt;();</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> Object source;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant for the default scope name: &#123;<span class="doctag">@code</span> &quot;&quot;&#125;, equivalent to singleton</span></span><br><span class="line"><span class="comment">     * status unless overridden from a parent bean definition (if applicable).</span></span><br><span class="line"><span class="comment">     * 默认bean作用域</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String SCOPE_DEFAULT = <span class="string">&quot;&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant that indicates no external autowiring at all.</span></span><br><span class="line"><span class="comment">     * 自动注入模式</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> #setAutowireMode</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant that indicates autowiring bean properties by name.</span></span><br><span class="line"><span class="comment">     * 自动注入通过bean名字</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> #setAutowireMode</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant that indicates autowiring bean properties by type.</span></span><br><span class="line"><span class="comment">     * 自动注入通过bean类型</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> #setAutowireMode</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant that indicates autowiring a constructor.</span></span><br><span class="line"><span class="comment">     * 自动注入通过构造函数</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> #setAutowireMode</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant that indicates determining an appropriate autowire strategy</span></span><br><span class="line"><span class="comment">     * through introspection of the bean class.</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> #setAutowireMode</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@deprecated</span> as of Spring 3.0: If you are using mixed autowiring strategies,</span></span><br><span class="line"><span class="comment">     * use annotation-based autowiring for clearer demarcation of autowiring needs.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="meta">@Deprecated</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant that indicates no dependency check at all.</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> #setDependencyCheck</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> DEPENDENCY_CHECK_NONE = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant that indicates dependency checking for object references.</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> #setDependencyCheck</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> DEPENDENCY_CHECK_OBJECTS = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant that indicates dependency checking for &quot;simple&quot; properties.</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> #setDependencyCheck</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> org.springframework.beans.BeanUtils#isSimpleProperty</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> DEPENDENCY_CHECK_SIMPLE = <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant that indicates dependency checking for all properties</span></span><br><span class="line"><span class="comment">     * (object references as well as &quot;simple&quot; properties).</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@see</span> #setDependencyCheck</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> DEPENDENCY_CHECK_ALL = <span class="number">3</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Constant that indicates the container should attempt to infer the</span></span><br><span class="line"><span class="comment">     * &#123;<span class="doctag">@link</span> #setDestroyMethodName destroy method name&#125; for a bean as opposed to</span></span><br><span class="line"><span class="comment">     * explicit specification of a method name. The value &#123;<span class="doctag">@value</span>&#125; is specifically</span></span><br><span class="line"><span class="comment">     * designed to include characters otherwise illegal in a method name, ensuring</span></span><br><span class="line"><span class="comment">     * no possibility of collisions with legitimately named methods having the same</span></span><br><span class="line"><span class="comment">     * name.</span></span><br><span class="line"><span class="comment">     * &lt;p&gt;Currently, the method names detected during destroy method inference</span></span><br><span class="line"><span class="comment">     * are &quot;close&quot; and &quot;shutdown&quot;, if present on the specific bean class.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String INFER_METHOD = <span class="string">&quot;(inferred)&quot;</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">volatile</span> Object beanClass;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> String scope = SCOPE_DEFAULT;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span> abstractFlag = <span class="keyword">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> Boolean lazyInit;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> autowireMode = AUTOWIRE_NO;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> dependencyCheck = DEPENDENCY_CHECK_NONE;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> String[] dependsOn;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span> autowireCandidate = <span class="keyword">true</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span> primary = <span class="keyword">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> Map&lt;String, AutowireCandidateQualifier&gt; qualifiers = <span class="keyword">new</span> LinkedHashMap&lt;&gt;();</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> Supplier&lt;?&gt; instanceSupplier;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span> nonPublicAccessAllowed = <span class="keyword">true</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span> lenientConstructorResolution = <span class="keyword">true</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> String factoryBeanName;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> String factoryMethodName;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> ConstructorArgumentValues constructorArgumentValues;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> MutablePropertyValues propertyValues;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> MethodOverrides methodOverrides = <span class="keyword">new</span> MethodOverrides();</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> String initMethodName;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> String destroyMethodName;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span> enforceInitMethod = <span class="keyword">true</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span> enforceDestroyMethod = <span class="keyword">true</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span> synthetic = <span class="keyword">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> role = BeanDefinition.ROLE_APPLICATION;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> String description;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> Resource resource;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> BeanDefinitionHolder decoratedDefinition;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> AnnotatedElement qualifiedElement;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Determines if the definition needs to be re-merged. */</span></span><br><span class="line"><span class="keyword">volatile</span> <span class="keyword">boolean</span> stale;</span><br><span class="line"></span><br><span class="line"><span class="keyword">boolean</span> allowCaching = <span class="keyword">true</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">boolean</span> isFactoryMethodUnique = <span class="keyword">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">volatile</span> ResolvableType targetType;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Package-visible field for caching the determined Class of a given bean definition. */</span></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">volatile</span> Class&lt;?&gt; resolvedTargetType;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Package-visible field for caching if the bean is a factory bean. */</span></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">volatile</span> Boolean isFactoryBean;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Package-visible field for caching the return type of a generically typed factory method. */</span></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">volatile</span> ResolvableType factoryMethodReturnType;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Package-visible field for caching a unique factory method candidate for introspection. */</span></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">volatile</span> Method factoryMethodToIntrospect;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Common lock for the four constructor fields below. */</span></span><br><span class="line"><span class="keyword">final</span> Object constructorArgumentLock = <span class="keyword">new</span> Object();</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Package-visible field for caching the resolved constructor or factory method. */</span></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line">Executable resolvedConstructorOrFactoryMethod;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Package-visible field that marks the constructor arguments as resolved. */</span></span><br><span class="line"><span class="keyword">boolean</span> constructorArgumentsResolved = <span class="keyword">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Package-visible field for caching fully resolved constructor arguments. */</span></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line">Object[] resolvedConstructorArguments;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Package-visible field for caching partly prepared constructor arguments. */</span></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line">Object[] preparedConstructorArguments;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Common lock for the two post-processing fields below. */</span></span><br><span class="line"><span class="keyword">final</span> Object postProcessingLock = <span class="keyword">new</span> Object();</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied. */</span></span><br><span class="line"><span class="keyword">boolean</span> postProcessed = <span class="keyword">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Package-visible field that indicates a before-instantiation post-processor having kicked in. */</span></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">volatile</span> Boolean beforeInstantiationResolved;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> Set&lt;Member&gt; externallyManagedConfigMembers;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> Set&lt;String&gt; externallyManagedInitMethods;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Nullable</span></span><br><span class="line"><span class="keyword">private</span> Set&lt;String&gt; externallyManagedDestroyMethods;</span><br></pre></td></tr></table></figure>


<h2 id="Spring-IoC体系结构"><a href="#Spring-IoC体系结构" class="headerlink" title="Spring IoC体系结构"></a>Spring IoC体系结构</h2><h3 id="BeanFactory"><a href="#BeanFactory" class="headerlink" title="BeanFactory"></a>BeanFactory</h3><p>Spring Bean的创建是典型的工厂模式，这一系列的Bean工厂也就是IoC容器为开发者管理对象间的依赖关系提供了很多的便利和基础服务，在Spring中有许多的实现提供用户选择和使用。最核心的类结构如下：</p>
<pre class="mermaid">graph BT

ListableBeanFactory --> BeanFactory
ConfigurableListableBeanFactory --> ListableBeanFactory
DefaultListableBeanFactory -.-> ConfigurableListableBeanFactory

HierarchicalBeanFactory --> BeanFactory
ConfigurableBeanFactory --> HierarchicalBeanFactory
ConfigurableListableBeanFactory --> ConfigurableBeanFactory

AutowireCapableBeanFactory --> BeanFactory
ConfigurableListableBeanFactory --> AutowireCapableBeanFactory

AbstractAutowireCapableBeanFactory -.-> ConfigurableBeanFactory
DefaultListableBeanFactory --> AbstractAutowireCapableBeanFactory</pre>

<p>其中<code>BeanFactory</code>作为顶层的接口，它定义了IoC容器的基本功能实现，比如<code>getBean()</code>方法就是这个接口定义的。<br>它有三个子类（或者是实现类），它们是：<code>ListableBeanFactory</code>、<code>HierarchicalBeanFactory</code>和<code>AutowireCapableBeanFactory</code>。但是从上图可以看到最终的默认实现类是<code>DefaultListableBeanFactory</code>。它实现了所有的接口，这样做的目的是什么呢？<br>查阅相关的资料可以发现，这些几个接口的实现都是有特定的使用场景的，它们主要是在Spring内部操作对象的传递和转换的过程中，对对象的数据访问所做的限制。比如<code>ListableBeanFactory</code>接口表示这些bean是可列表的；<code>HierarchicalBeanFactory</code>表示这些bean是有继承关系的，也就是说这些bean是可能有父类bean；<code>AutowireCapableBeanFactory</code>接口定义了bean的自动装配规则。这四个接口共同定义了Bean的集合，Bean之间的关系，Bean的行为，从而组成了IoC容器的基本结构。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">BeanFactory</span> </span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 对FactoryBean的转义定义，如果使用beanName获取到的是FactoryBean接口中getObject()方法返回的实例</span></span><br><span class="line"><span class="comment">     * 如果要拿到FactoryBean本身则需要加上&amp;前缀，applicationContext.getBean(&amp;beanName)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    String FACTORY_BEAN_PREFIX = <span class="string">&quot;&amp;&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据beanName获取容器中实例化好的bean</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function">Object <span class="title">getBean</span><span class="params">(String name)</span> <span class="keyword">throws</span> BeansException</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据bean的名字和Class类型来得到bean实例，增加了类型安全验证机制。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    &lt;T&gt; <span class="function">T <span class="title">getBean</span><span class="params">(String name, Class&lt;T&gt; requiredType)</span> <span class="keyword">throws</span> BeansException</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取bean实例时可以传递构造方法的参数，args就是构造方法的参数。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function">Object <span class="title">getBean</span><span class="params">(String name, Object... args)</span> <span class="keyword">throws</span> BeansException</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据bean的类型获取bean实例。比如getBean(User.class)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    &lt;T&gt; <span class="function">T <span class="title">getBean</span><span class="params">(Class&lt;T&gt; requiredType)</span> <span class="keyword">throws</span> BeansException</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据bean的类型和构造函数的参数获取bean实例。比如getBean(User.class, age, name)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    &lt;T&gt; <span class="function">T <span class="title">getBean</span><span class="params">(Class&lt;T&gt; requiredType, Object... args)</span> <span class="keyword">throws</span> BeansException</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取一个提供器类型的bean，通常是Spring框架内部使用。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    &lt;T&gt; <span class="function">ObjectProvider&lt;T&gt; <span class="title">getBeanProvider</span><span class="params">(Class&lt;T&gt; requiredType)</span></span>;</span><br><span class="line"></span><br><span class="line">    &lt;T&gt; <span class="function">ObjectProvider&lt;T&gt; <span class="title">getBeanProvider</span><span class="params">(ResolvableType requiredType)</span></span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 提供对bean的检索，看看是否在IOC容器有这个名字的bean</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">containsBean</span><span class="params">(String name)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">isSingleton</span><span class="params">(String name)</span> <span class="keyword">throws</span> NoSuchBeanDefinitionException</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">isPrototype</span><span class="params">(String name)</span> <span class="keyword">throws</span> NoSuchBeanDefinitionException</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">isTypeMatch</span><span class="params">(String name, Class&lt;?&gt; typeToMatch)</span> <span class="keyword">throws</span> NoSuchBeanDefinitionException</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 得到bean实例的Class类型</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Nullable</span></span><br><span class="line">    Class&lt;?&gt; getType(String name) <span class="keyword">throws</span> NoSuchBeanDefinitionException;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Nullable</span></span><br><span class="line">    Class&lt;?&gt; getType(String name, <span class="keyword">boolean</span> allowFactoryBeanInit) <span class="keyword">throws</span> NoSuchBeanDefinitionException;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 得到bean的别名，如果根据别名检索，那么其原名也会被检索出来    </span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    String[] getAliases(String name);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>FactoryBean</code>只定义了IoC容器的基本行为，它并不关心bean是如何定义，怎么加载的。<br>而具体是定义和加载是在其他的实现类中处理的，比如<code>XmlBeanFactory</code>、<code>ClasspathXmlApplicationContext</code>等。<br><code>XmlBeanFactory</code>是容器的最基本实现（<em>但是目前这个类已经声明为过时</em>），其他的加载类都是在此基础上的扩展。</p>
<h4 id="BeanDefinition（bean定义信息，IoC核心数据结构）"><a href="#BeanDefinition（bean定义信息，IoC核心数据结构）" class="headerlink" title="BeanDefinition（bean定义信息，IoC核心数据结构）"></a>BeanDefinition（bean定义信息，IoC核心数据结构）</h4><p>Spring容器管理了我们定义的各种bean对象及其相互关系，bean在对象实现是以<code>BeanDefinition</code>类描述的。</p>
<pre class="mermaid">graph BT

AttributeAccessorSupport -.-> AttributeAccessor
BeanMatadataAttributeAccessor --> AttributeAccessorSupport
BeanMatadataAttributeAccessor -.-> BeanMatadataElement
AbstractBeanDefinition --> BeanMatadataAttributeAccessor
RootBeanDefinition --> AbstractBeanDefinition
GenericBeanDefinition --> AbstractBeanDefinition
ChildBeanDefinition --> AbstractBeanDefinition

BeanDefinition --> AttributeAccessor
BeanDefinition --> BeanMatadataElement
AbstractBeanDefinition -.-> BeanDefinition</pre>

<p>Bean的解析过程非常复杂，功能被分的很细，因为这里需要被扩展的地方非常多，也提供了很多接口给开发者用于修改bean的定义。保证了足够的灵活性，以应对变化。Bean的解析主要是对Spring配置文件或者配置类的解析，解析过程如下：</p>
<pre class="mermaid">graph BT
XmlBeanDefinitionReader --> AbstractBeanDefinitionReader
AbstractBeanDefinitionReader -.-> BeanDefinitionReader

XmlBeanDefinitionReader -.-> DefaultBeanDefinitionDocumentReader
DefaultBeanDefinitionDocumentReader -.-> BeanDefinitionDocumentReader

XmlBeanDefinitionReader -.-> BeanDefinitionDocumentReader</pre>



<h2 id="IoC-容器初始化、bean实例化（核心内容）"><a href="#IoC-容器初始化、bean实例化（核心内容）" class="headerlink" title="IoC 容器初始化、bean实例化（核心内容）"></a>IoC 容器初始化、bean实例化（核心内容）</h2><p>这部分是非常非常复杂，在另外一篇《Spring IoC原理》中详细介绍。</p>

    </div>

      
    <div class="post-nav">
      <div class="post-nav-item post-nav-next">
        
          <span>〈 </span>
          <a href="/2020/05/04/JVM/%E8%99%9A%E6%8B%9F%E6%9C%BA/" rel="next" title="Java虚拟机">
          Java虚拟机
          </a>
        
      </div>
  
      <div class="post-nav-item post-nav-prev">
          
          <a href="/2020/07/17/Spring/Spring%E6%87%92%E5%8A%A0%E8%BD%BD%E9%AA%8C%E8%AF%81/" rel="prev" title="懒加载的几个疑问？？">
            懒加载的几个疑问？？
          </a>
          <span>〉</span>
        
      </div>
    </div>
  
  </article>
  <div class="toc-container">
    
  <div id="toc" class="toc-article">
    <strong class="toc-title">目录</strong>
    <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#Spring-Framework5-x"><span class="toc-text">Spring Framework5.x</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#BeanDefinition%E5%AF%B9%E8%B1%A1"><span class="toc-text">BeanDefinition对象</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Spring-IoC%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84"><span class="toc-text">Spring IoC体系结构</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#BeanFactory"><span class="toc-text">BeanFactory</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#BeanDefinition%EF%BC%88bean%E5%AE%9A%E4%B9%89%E4%BF%A1%E6%81%AF%EF%BC%8CIoC%E6%A0%B8%E5%BF%83%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%EF%BC%89"><span class="toc-text">BeanDefinition（bean定义信息，IoC核心数据结构）</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#IoC-%E5%AE%B9%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E3%80%81bean%E5%AE%9E%E4%BE%8B%E5%8C%96%EF%BC%88%E6%A0%B8%E5%BF%83%E5%86%85%E5%AE%B9%EF%BC%89"><span class="toc-text">IoC 容器初始化、bean实例化（核心内容）</span></a></li></ol></li></ol>
  </div>


  </div>
</div>


<div class="copyright">
    <span>本作品采用</span>
    <a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by/4.0/">知识共享署名 4.0 国际许可协议</a>
    <span>进行许可。 转载时请注明原文链接。</span>
</div>
<div class="share">

</div>
<div class="post-container">
    <article class="post">
      <div id="container"></div>
    </article>
</div>

<link rel="stylesheet" href="https://imsun.github.io/gitment/style/default.css">
<script src="https://imsun.github.io/gitment/dist/gitment.browser.js"></script>
<script>
var gitment = new Gitment({
  id: 'Spring Framework5.x', // 可选。默认为 location.href
  owner: 'ubuntuvim',
  repo: 'ubuntuvim.github.io',
  oauth: {
    client_id: '48b3df0bf4ba1743e0a3',
    client_secret: 'c6c2cec09acb5eecc9d325d56cef187264aa1e16',
  },
})
gitment.render('container')
</script>



    </div>

    

  </div>
  <footer class="footer text-center">
    <div id="bottom-inner">
        <a class="bottom-item" href="http://xcoding.tech/">首页</a> |
        <a class="bottom-item" href="http://xcoding.tech/" target="_blank">主站</a> |
        <a class="bottom-item" href="https://github.com/ubuntuvim" target="_blank">GitHub</a> |
        <a class="bottom-item" href="https://hexo.io" target="_blank">Powered by hexo</a> |
        <a class="bottom-item" href="https://github.com/KevinOfNeu/hexo-theme-xoxo" target="_blank">Theme xoxo</a>
    </div>
</footer>


  <script src='https://unpkg.com/mermaid@7.1.2/dist/mermaid.min.js'></script>
  <script>
    if (window.mermaid) {
      mermaid.initialize({theme: 'forest'});
    }
  </script>


  
  <!-- scripts list from theme config.yml -->
  
    <script src="/js/zepto.min.js"></script>
  


<script>
  (function(window, document, undefined) {

    var timer = null;

    function returnTop() {
      cancelAnimationFrame(timer);
      timer = requestAnimationFrame(function fn() {
        var oTop = document.body.scrollTop || document.documentElement.scrollTop;
        if (oTop > 0) {
          document.body.scrollTop = document.documentElement.scrollTop = oTop - 50;
          timer = requestAnimationFrame(fn);
        } else {
          cancelAnimationFrame(timer);
        }
      });
    }

    var hearts = [];
    window.requestAnimationFrame = (function() {
      return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        function(callback) {
          setTimeout(callback, 1000 / 60);
        }
    })();
    init();

    function init() {
      css(".heart{z-index:9999;width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: absolute;}.heart:after{top: -5px;}.heart:before{left: -5px;}");
      attachEvent();
      gameloop();
      addMenuEvent();
    }

    function gameloop() {
      for (var i = 0; i < hearts.length; i++) {
        if (hearts[i].alpha <= 0) {
          document.body.removeChild(hearts[i].el);
          hearts.splice(i, 1);
          continue;
        }
        hearts[i].y--;
        hearts[i].scale += 0.004;
        hearts[i].alpha -= 0.013;
        hearts[i].el.style.cssText = "left:" + hearts[i].x + "px;top:" + hearts[i].y + "px;opacity:" + hearts[i].alpha + ";transform:scale(" + hearts[i].scale + "," + hearts[i].scale + ") rotate(45deg);background:" + hearts[i].color;
      }
      requestAnimationFrame(gameloop);
    }

    /**
     * 给logo设置点击事件
     * 
     * - 回到顶部
     * - 出现爱心
     */
    function attachEvent() {
      var old = typeof window.onclick === "function" && window.onclick;
      var logo = document.getElementById("logo");
      if (logo) {
        logo.onclick = function(event) {
          returnTop();
          old && old();
          createHeart(event);
        }
      }
      
    }

    function createHeart(event) {
      var d = document.createElement("div");
      d.className = "heart";
      hearts.push({
        el: d,
        x: event.clientX - 5,
        y: event.clientY - 5,
        scale: 1,
        alpha: 1,
        color: randomColor()
      });
      document.body.appendChild(d);
    }

    function css(css) {
      var style = document.createElement("style");
      style.type = "text/css";
      try {
        style.appendChild(document.createTextNode(css));
      } catch (ex) {
        style.styleSheet.cssText = css;
      }
      document.getElementsByTagName('head')[0].appendChild(style);
    }

    function randomColor() {
      // return "rgb(" + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + ")";
      return "#F44336";
    }

    function addMenuEvent() {
      var menu = document.getElementById('menu-main-post');
      if (menu) {
        var toc = document.getElementById('toc');
        if (toc) {
          menu.onclick = function() {
            if (toc) {
              if (toc.style.display == 'block') {
                toc.style.display = 'none';
              } else {
                toc.style.display = 'block';
              }
            }
          };
        } else {
          menu.style.display = 'none';
        }
      }
    }

  })(window, document);
</script>

  



</body>
</html>
